import enum
from base.exception.IllegalArgumentException import IllegalArgumentException

class TYPES:
    T_PTR = 0
    T_DOUBLE = 0x40
    T_INTEGER = 1
    T_DECIMAL = 2
    T_FLOAT = 3
    T_DATETIME = 5
    T_DATETIMESTAMP = 6
    T_DATE = 7
    T_BOOLEAN = 8
    T_SHORTSTRING = 9

    T_POSITIVE_INTEGER = 10
    T_NEGATIVE_INTEGER = 11
    T_NON_NEGATIVE_INTEGER = 12
    T_NON_POSITIVE_INTEGER = 13
    T_LONG = 14
    T_INT = 15
    T_SHORT = 16
    T_BYTE = 17
    T_UNSIGNEDLONG = 18
    T_UNSIGNEDINT = 19
    T_UNSIGNEDSHORT = 20
    T_UNSIGNEDBYTE = 21

    # Never stored : bits 1011 0000 so as not to look like a double.
    T_SPECIAL = 0x30
    T_INVALID = 0x31

    T_EXTENSION = 0x3F

class NodeIdType(enum.Enum):
    PTR = TYPES.T_PTR, None
    XSD_INTEGER = TYPES.T_INTEGER, "Integer"
    XSD_DECIMAL = TYPES.T_DECIMAL, "Decimal"
    XSD_FLOAT = TYPES.T_FLOAT, "Float"
    XSD_DOUBLE = TYPES.T_DOUBLE, "Double"
    XSD_DATETIME = TYPES.T_DATETIME, "DateTime"
    XSD_DATETIMESTAMP = TYPES.T_DATETIMESTAMP, "DateTimeStamp"
    XSD_DATE = TYPES.T_DATE, "Date"
    XSD_BOOLEAN = TYPES.T_BOOLEAN, "Boolean"
    XSD_SHORTSTRING = TYPES.T_SHORTSTRING, "ShortString"
    # 1 and greater
    XSD_POSITIVE_INTEGER = TYPES.T_POSITIVE_INTEGER, "Positive Integer"
    # -1 and down
    XSD_NEGATIVE_INTEGER = TYPES.T_NEGATIVE_INTEGER, "Negative Integer"
    # postive and zero
    XSD_NON_NEGATIVE_INTEGER = TYPES.T_NON_NEGATIVE_INTEGER, "Non-negative Integer"
    # negative or zero
    XSD_NON_POSITIVE_INTEGER = TYPES.T_NON_POSITIVE_INTEGER, "Non-positive Integer"
    XSD_LONG = TYPES.T_LONG, "Long"
    XSD_INT = TYPES.T_INT, "Int"
    XSD_SHORT = TYPES.T_SHORT, "Short"
    XSD_BYTE = TYPES.T_BYTE, "Byte"
    XSD_UNSIGNEDLONG = TYPES.T_UNSIGNEDLONG, "UnsignedLong"
    XSD_UNSIGNEDINT = TYPES.T_UNSIGNEDINT, "UnsignedInt"
    XSD_UNSIGNEDSHORT = TYPES.T_UNSIGNEDSHORT, "UnsignedShort"
    XSD_UNSIGNEDBYTE = TYPES.T_UNSIGNEDBYTE, "UnsignedByte"

    # Never stored.
    SPECIAL = TYPES.T_SPECIAL, "Special"
    # Used here only.
    INVALID_ = TYPES.T_INVALID, "Invalid"

    def __init__(self, types, displayName):
        self._value = types
        self._displayName = displayName

    @property
    def value(self):
        return self._value

    @property
    def displayName(self):
        return self._displayName

    '''
     * @param type NodeIdType
     * @return boolean
    '''
    @staticmethod
    def isStorable(type):
        return not NodeIdType.isSpecial(type)


    '''
     * @param type NodeIdType
     * @return boolean
    '''
    @staticmethod
    def isDecimal(type):
        return type == NodeIdType.XSD_DECIMAL


    '''
     * @param type NodeIdType
     * @return boolean
    '''
    @staticmethod
    def isDouble(type):
        return type == NodeIdType.XSD_DOUBLE


    '''
     * @param type NodeIdType
     * @return boolean
    '''
    @staticmethod
    def isFloat(type):
        return type == NodeIdType.XSD_FLOAT


    '''
     * @param type NodeIdType
     * @return boolean
    '''
    @staticmethod
    def isSpecial(type):
        return type == NodeIdType.SPECIAL


    '''
     * @param type NodeIdType
     * @return boolean
    '''
    @staticmethod
    def isInline(type):
        type_list = [NodeIdType.XSD_INTEGER, NodeIdType.XSD_DECIMAL, NodeIdType.XSD_DOUBLE, NodeIdType.XSD_FLOAT, NodeIdType.XSD_DATETIME, NodeIdType.XSD_DATETIMESTAMP,
                     NodeIdType.XSD_DATE, NodeIdType.XSD_BOOLEAN, NodeIdType.XSD_SHORTSTRING, NodeIdType.XSD_POSITIVE_INTEGER, NodeIdType.XSD_NEGATIVE_INTEGER,
                     NodeIdType.XSD_NON_NEGATIVE_INTEGER, NodeIdType.XSD_NON_POSITIVE_INTEGER, NodeIdType.XSD_LONG, NodeIdType.XSD_INT, NodeIdType.XSD_SHORT,
                     NodeIdType.XSD_BYTE, NodeIdType.XSD_UNSIGNEDLONG, NodeIdType.XSD_UNSIGNEDINT, NodeIdType.XSD_UNSIGNEDSHORT, NodeIdType.XSD_UNSIGNEDBYTE]
        if (type in type_list):
            return True
        return False

    '''
     * @param x int
     * @return NodeIdType
    '''
    @staticmethod
    def intToEnum(x):
        if (x >= 0x80):
            raise IllegalArgumentException("Value '" + x + "' not legal: too large")
        if (x != 0):
            pass
        t = NodeIdType.intToEnum_(x)
        if (t == NodeIdType.INVALID_):
            raise IllegalArgumentException("Value '" + x + "' not legal for NodeIdType")
        return t


    '''
     * @param x int
     * @return NodeIdType
    '''
    @staticmethod
    def intToEnum_(x):
        #x = TYPES.enc(x)
        if (x == NodeIdType.PTR.value): return NodeIdType.PTR
        # XSD_DOUBL is special encoded - handled elsewhere.
        if (x == NodeIdType.XSD_DOUBLE.value): return NodeIdType.XSD_DOUBLE
        if (x == NodeIdType.XSD_INTEGER.value): return NodeIdType.XSD_INTEGER
        if (x == NodeIdType.XSD_DECIMAL.value): return NodeIdType.XSD_DECIMAL
        if (x == NodeIdType.XSD_FLOAT.value): return NodeIdType.XSD_FLOAT

        if (x == NodeIdType.XSD_DATETIME.value): return NodeIdType.XSD_DATETIME
        if (x == NodeIdType.XSD_DATETIMESTAMP.value): return NodeIdType.XSD_DATETIMESTAMP
        if (x == NodeIdType.XSD_DATE.value): return NodeIdType.XSD_DATE

        if (x == NodeIdType.XSD_BOOLEAN.value): return NodeIdType.XSD_BOOLEAN
        if (x == NodeIdType.XSD_SHORTSTRING.value): return NodeIdType.XSD_SHORTSTRING

        if (x == NodeIdType.XSD_POSITIVE_INTEGER.value): return NodeIdType.XSD_POSITIVE_INTEGER
        if (x == NodeIdType.XSD_NEGATIVE_INTEGER.value): return NodeIdType.XSD_NEGATIVE_INTEGER
        if (x == NodeIdType.XSD_NON_NEGATIVE_INTEGER.value): return NodeIdType.XSD_NON_NEGATIVE_INTEGER
        if (x == NodeIdType.XSD_NON_POSITIVE_INTEGER.value): return NodeIdType.XSD_NON_POSITIVE_INTEGER

        if (x == NodeIdType.XSD_LONG.value): return NodeIdType.XSD_LONG
        if (x == NodeIdType.XSD_INT.value): return NodeIdType.XSD_INT
        if (x == NodeIdType.XSD_SHORT.value): return NodeIdType.XSD_SHORT
        if (x == NodeIdType.XSD_BYTE.value): return NodeIdType.XSD_BYTE
        if (x == NodeIdType.XSD_UNSIGNEDLONG.value): return NodeIdType.XSD_UNSIGNEDLONG
        if (x == NodeIdType.XSD_UNSIGNEDINT.value): return NodeIdType.XSD_UNSIGNEDINT
        if (x == NodeIdType.XSD_UNSIGNEDSHORT.value): return NodeIdType.XSD_UNSIGNEDSHORT
        if (x == NodeIdType.XSD_UNSIGNEDBYTE.value): return NodeIdType.XSD_UNSIGNEDBYTE
        # if (x == EXTENSION.value ) return EXTENSION
        return NodeIdType.INVALID_